/* $Id: cache.cc jjs $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 or any
   later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/
#define DEBUG_ROUTINE "cache"
#include <iostream>
#include "../general/hashtable.h"
#include "../general/log.h"
#include "cache.h"

using namespace std;

#define min(a,b) (((a)<(b))?(a):(b))

picture::picture(std::string k) {
    dbg_state("Reading image: %s", k.c_str());
    image=Gdk::Pixbuf::create_from_file(k);
    higher=NULL;
    lower=NULL;
    key=k;
}

cache::cache(): data(1000) {
    lowest=NULL;
    highest=NULL;
    elements=0;
}

picture& cache::operator[](std::string key) {
    picture *n=data[key.c_str()];
    if (n==NULL) {
        elements++;
        n=new picture("/var/lib/moros/images/"+key);
        data.insert(key.c_str(), n);
    } else {
        if (n->lower != NULL) {
            n->lower->higher=n->higher;
        } else {
            lowest=n->higher;
        }
        if (n->higher != NULL) {
            n->higher->lower=n->lower;
            n->higher=NULL;
        }
    }
    n->lower=highest;
    if (highest != NULL) highest->higher=n;
    if (lowest == NULL) lowest=n;
    highest=n;
    return *n;
}

bool cache::exists(std::string key) {
    return data[key.c_str()]!=NULL;
}

void cache::clean(int m) {
    int t;
    int cnr=min(elements-m,10);
    for (t=0; t<cnr; t++) {
        picture *n=lowest->higher;
        data.remove(lowest->key.c_str());
        delete lowest;
        if (n!=NULL) n->lower=NULL;
        else highest=NULL;
        lowest=n;
        elements--;
    }
}

void cache::dump() {
    picture *n=highest;
    cout << "Dump with " << elements << " elements\n";
    while(n!=NULL) {
        cout << "  " << n->key << endl;
        if (n->lower != NULL) {
            if (n->lower->higher != n) {
                cout << "  Something is rotten\n";
            }
        } else {
            if (n != lowest) {
                cout << "  Highest isn't correct\n";
            }
        }
        n=n->lower;
    }
    cout << "Finished\n\n";
}
